package com.iflytek.jzcpx.procuracy.ocr.common;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;

import com.iflytek.jzcpx.procuracy.ocr.common.enums.StateEnums;

/**
 * <p>
 * 二进制流工具类
 * </p>
 *
 * @author 谢海龙
 * @since 2019-08-16
 */
public class ByteUtil {
    /**
     * 字符串转字节数组
     * <example>
     * ByteUtil.string2Bytes("1",1); // success
     * ByteUtil.string2Bytes("你好中国",200); //message
     * </example>
     *
     * @param str    字符串
     * @param length 目标字节数组长度
     * @return 字节数组
     * @throws UnsupportedEncodingException
     */
    private static byte[] string2Bytes(String str, int length) throws UnsupportedEncodingException {
        byte[] dst = new byte[length];
        byte[] src = str.getBytes("UTF-8");
        System.arraycopy(src, 0, dst, 0, src.length);
        return dst;
    }

    /**
     * 状态码转字节数组
     *
     * @param state 状态码
     * @return 字节数组
     */
    private static byte[] state2Bytes(int state) {
        byte[] stateByte = new byte[1];
        stateByte[0] = (byte) state;
        return stateByte;
    }

    /**
     * long转字节数组
     *
     * @param datalength long值
     * @param length     目标字节数组长度
     * @return 字节数组
     */
    private static byte[] long2Bytes(long datalength, int length) {
        ByteBuffer buffer = ByteBuffer.allocate(length);
        buffer.putLong(0, datalength);
        return buffer.array();
    }

    /**
     * 字节数组转long
     *
     * @param bytes 字节数组
     * @return long
     */
    public static long bytes2Long(byte[] bytes) {
        ByteBuffer buffer = ByteBuffer.allocate(Long.BYTES);
        buffer.put(bytes);
        buffer.flip();
        return buffer.getLong();
    }

    /**
     * 获取目标字节对应的元素字节数组
     * <example>
     * ByteUtil.interceptBytes(完整字节数组, 0, 1) // 获取 success
     * ByteUtil.interceptBytes(完整字节数组, 1, 8) // 获取 数据部分的长度
     * </example>
     *
     * @param soureByte 原始数组
     * @param off       偏移量
     * @param length    长度
     * @return 元素字节数组
     */
    public static byte[] interceptBytes(byte[] soureByte, int off, int length) {
        byte[] result = new byte[length];
        System.arraycopy(soureByte, off, result, 0, length);
        return result;
    }

    /**
     * 拼接字节流
     * <example>
     * ByteUtil.concatBytes(successBytes, messageBytes...)
     * </example>
     *
     * @param bytess
     * @return
     */
    private static byte[] concatBytes(byte[]... bytess) {
        int len = 0;
        for (byte[] bytes : bytess) {
            if (bytes != null) {
                len += bytes.length;
            }
        }
        byte[] result = new byte[len];
        int idx = 0;
        for (byte[] bytes : bytess) {
            if (bytes != null) {
                System.arraycopy(bytes, 0, result, idx, bytes.length);
                idx += bytes.length;
            }
        }
        return result;
    }

    /**
     * bytes 数组转字符串
     * <example>
     * ByteUtil.bytes2String(messageBytes)
     * </example>
     *
     * @param bytes
     * @return
     */
    public static String bytes2String(byte[] bytes) throws UnsupportedEncodingException {
        int len = 0;
        for (int i = 0; i < bytes.length; i++) {
            if (bytes[i] == 0) {
                len = i;
                break;
            }
        }
        return new String(bytes, 0, len, "UTF-8");
    }

    /**
     * 获取二进制流
     *
     * @param state      状态
     * @param datalength 数据部分的长度
     * @param params     参数
     * @param message    提示消息
     * @param data       文件数据流
     * @return 二进制流
     * @throws UnsupportedEncodingException
     */
    public static byte[] getBytes(StateEnums state, int datalength, String params, String message, byte[] data) throws UnsupportedEncodingException {

        byte[] successByte = ByteUtil.state2Bytes(state.getDesc());
        byte[] datalengthByte = ByteUtil.long2Bytes(datalength, 8);

        Long dataSize = ByteUtil.bytes2Long(datalengthByte);

        byte[] codeByte = ByteUtil.string2Bytes(state.getCode(), 91);
        byte[] paramsByte = params == null ? null : ByteUtil.string2Bytes(params, 200);
        byte[] messageByte = message == null ? null : ByteUtil.string2Bytes(message, 200);

        return concatBytes(successByte, datalengthByte, codeByte, paramsByte, messageByte, data);
    }

    public static byte[] getBytes(StateEnums state, int datalength, String params, String message) throws UnsupportedEncodingException {
        return getBytes(state, datalength, params, message, null);
    }

    public static byte[] getBytes(StateEnums state, int datalength, String message, byte[] data) throws UnsupportedEncodingException {
        return getBytes(state, datalength, null, message, data);
    }

    public static byte[] getBytes(StateEnums state, int datalength, String message) throws UnsupportedEncodingException {
        return getBytes(state, datalength, null, message, null);
    }

}
